/*
 * Copyright 2017 Zhihu Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.xiaoyu.media.matisse.internal.ui

import android.content.Context
import android.database.Cursor
import android.os.Bundle
import android.os.Parcelable
import androidx.fragment.app.Fragment
import androidx.appcompat.app.AppCompatDelegate
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup

import com.xiaoyu.media.matisse.internal.entity.Album
import com.xiaoyu.media.matisse.internal.entity.Item
import com.xiaoyu.media.matisse.internal.entity.SelectionSpec
import com.xiaoyu.media.matisse.internal.model.AlbumMediaCollection
import com.xiaoyu.media.matisse.internal.model.SelectedItemCollection
import com.xiaoyu.media.matisse.internal.ui.adapter.AlbumMediaAdapter
import com.xiaoyu.media.matisse.internal.ui.widget.MediaGridInset
import com.xiaoyu.media.matisse.internal.utils.UIUtils
import com.xiaoyu.media.R

class MediaSelectionFragment : Fragment(), AlbumMediaCollection.AlbumMediaCallbacks, AlbumMediaAdapter.CheckStateListener, AlbumMediaAdapter.OnMediaClickListener {

    private val mAlbumMediaCollection = AlbumMediaCollection()
    private var mRecyclerView: RecyclerView? = null
    private var mAdapter: AlbumMediaAdapter? = null
    private var mSelectionProvider: SelectionProvider? = null
    private var mCheckStateListener: AlbumMediaAdapter.CheckStateListener? = null
    private var mOnMediaClickListener: AlbumMediaAdapter.OnMediaClickListener? = null

    override fun onAttach(context: Context) {
        super.onAttach(context)
        if (context is SelectionProvider) {
            mSelectionProvider = context
        } else {
            throw IllegalStateException("Context must implement SelectionProvider.")
        }
        if (context is AlbumMediaAdapter.CheckStateListener) {
            mCheckStateListener = context
        }
        if (context is AlbumMediaAdapter.OnMediaClickListener) {
            mOnMediaClickListener = context
        }
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.matisse_fragment_media_selection, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        mRecyclerView = view.findViewById<View>(R.id.recyclerview) as RecyclerView
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        val album = arguments?.getParcelable<Album>(EXTRA_ALBUM)

        mAdapter = context?.let {
            mSelectionProvider?.provideSelectedItemCollection()?.let { it1 ->
                mRecyclerView?.let { it2 ->
                    AlbumMediaAdapter(it, it1, it2)
                }
            }
        }
        mAdapter?.registerCheckStateListener(this)
        mAdapter?.registerOnMediaClickListener(this)
        mRecyclerView?.setHasFixedSize(true)

        var spanCount: Int
        val selectionSpec = SelectionSpec.instance
        spanCount = if (selectionSpec.gridExpectedSize > 0) {
            context?.let { UIUtils.spanCount(it, selectionSpec.gridExpectedSize) } ?: 3
        } else {
            selectionSpec.spanCount
        }
        if (spanCount <= 0) {
            spanCount = 3
        }
        mRecyclerView?.layoutManager = GridLayoutManager(context, spanCount)

        val spacing = resources.getDimensionPixelSize(R.dimen.media_grid_spacing)
        mRecyclerView?.addItemDecoration(MediaGridInset(spanCount, spacing, false))
        mRecyclerView?.adapter = mAdapter
        activity?.let { mAlbumMediaCollection.onCreate(it, this) }
        mAlbumMediaCollection.load(album, selectionSpec.capture)
    }

    override fun onDestroyView() {
        super.onDestroyView()
        mAlbumMediaCollection.onDestroy()
    }

    fun refreshMediaGrid() {
        mAdapter?.notifyDataSetChanged()
    }

    fun refreshSelection() {
        mAdapter?.refreshSelection()
    }

    override fun onAlbumMediaLoad(cursor: Cursor) {
        mAdapter?.swapCursor(cursor)
    }

    override fun onAlbumMediaReset() {
        mAdapter?.swapCursor(null)
    }

    override fun onUpdate() {
        // notify outer Activity that check state changed
        if (mCheckStateListener != null) {
            mCheckStateListener?.onUpdate()
        }
    }

    override fun onMediaClick(album: Album?, item: Item?, adapterPosition: Int) {
        if (mOnMediaClickListener != null) {
            mOnMediaClickListener?.onMediaClick(arguments?.getParcelable<Parcelable>(EXTRA_ALBUM) as Album,
                    item, adapterPosition)
        }
    }

    interface SelectionProvider {
        fun provideSelectedItemCollection(): SelectedItemCollection
    }

    companion object {

        const val EXTRA_ALBUM = "extra_album"

        init {
            AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
        }

        fun newInstance(album: Album): MediaSelectionFragment {
            val fragment = MediaSelectionFragment()
            val args = Bundle()
            args.putParcelable(EXTRA_ALBUM, album)
            fragment.arguments = args
            return fragment
        }
    }
}
